#include "psLightSource.h"
#include <math.h>
#include "Drawer.h"


HW2::psLightSource::psLightSource(void)
{
	 //type = 'p';
		 color.r = 255;
		 color.g = 255;
		 color.b = 255;
		 
		 enabled = false;
		 isInViewMode =true;
		 Coordinates c(0,0,0);

		 shadowVerification =0;
		/* for(int i= 0 ; i<100000;i++){
			 ShadowDirectionVec.push_back(c);
			 ShadowPointsVec.push_back(c);

		 }*/
		
		//unsigned __int16* t = new unsigned __int16[100000000];
		/* dirX = new int[1000000];
		 dirY = new int[1000000];
		 dirZ = new int[1000000];*/
}




HW2::Coordinates HW2::psLightSource::getDirectionFromPoint(HW2::Coordinates& toPoint){
	HW2::Coordinates tmp(0,0,0);
	tmp = toPoint.sub(position);
	
	tmp.makeUnitVec();
	return tmp;

	
}


double HW2::psLightSource::getDistanceFromPoint(Coordinates& toPoint){
	return (toPoint.sub(position)).norm();
}
/*HW2::psLightSource::psLightSource(int xPod , int yPos ,int zPos, int xDir, int yDir  , int zDir 
			,char ntype ){
	

			//	 positionCoordinates ;
		// type = ntype;
}*/
HW2::psLightSource::~psLightSource(void)
{
}



void HW2::psLightSource::setPosition(double x,double y, double z){

	HW2::Drawer &d = HW2::Drawer::get();
	originalPosition.X() = x;
	originalPosition.Y() = y;
	originalPosition.Z() = z;
	Coordinates tmp(x,y,z);
	
	//HW2::Drawer &d = HW2::Drawer::get();
	if (!isInViewMode){
		tmp = d.transform(tmp);

		position = tmp;
	}else{

		position = tmp;

	}

}


void  HW2::psLightSource::transformLightSources(){
	HW2::Drawer &d = HW2::Drawer::get();
	direction = d.transform(originalDirection);
	position = d.transform(originalPosition);

	double norm = sqrt(direction.X()*direction.X() + direction.Y()*direction.Y() + direction.Z()*direction.Z());
	direction.X() = direction.X() / norm;
	direction.Y() = direction.Y() / norm;
	direction.Z() = direction.Z() / norm;
}

void HW2::psLightSource::setDirection(double x,double y, double z){
	/*direction.X() = x - position.X();
	direction.Y() = y - position.Y();
	direction.Z() = z - position.Z();

	double norm = sqrt(direction.X()*direction.X() + direction.Y()*direction.Y() + direction.Z()*direction.Z());
	if (norm == 0)
		norm = 1;
	direction.X() = direction.X()/norm;
	direction.Y() = direction.Y()/norm;
	direction.Z() = direction.Z()/norm;*/
	HW2::Drawer &d = HW2::Drawer::get();
	originalDirection.X() = x;
	originalDirection.Y() = y;
	originalDirection.Z() = z;

	displayDirection.X() = x;
	displayDirection.Y() = y;
	displayDirection.Z() = z;


	
	

	double norm = sqrt(x*x + y*y + z*z);
	if (norm == 0)
		norm = 1;
	originalDirection.X() = x/norm;
	originalDirection.Y() = y/norm;
	originalDirection.Z() = z/norm;

	if (!isInViewMode){
		direction = d.transform(originalDirection);
		norm = sqrt(direction.X()*direction.X() + direction.Y()*direction.Y() + direction.Z()*direction.Z());
		direction.X() = direction.X() / norm;
		direction.Y() = direction.Y() / norm;
		direction.Z() = direction.Z() / norm;	
	}else{


		direction.X() = originalDirection.X();
		direction.Y() = originalDirection.Y();
		direction.Z() = originalDirection.Z();	

	}
}


void HW2::psLightSource::setViewMode( LightSpace mode){

/*	if (mode == LIGHT_SPACE_VIEW){
		

		direction = originalDirection;
		position = originalPosition;
		isInViewMode = true;

	}else if (mode == LIGHT_SPACE_LOCAL){
		isInViewMode = false;
		transformLightSources();

	}*/


}



void HW2::psLightSource::setColor(double r, double g, double b){

	Color c(r,g,b);
	color = c;

}


int HW2::psLightSource::getIndex(Coordinates& direct){
	int j = 0;

	
	
	int z = direct.Z() < 0 ? (-direct.Z()*100):(direct.Z()*100) ;	
	int y = direct.Y() < 0 ? (-direct.Y()*100):(direct.Y()*100) ;
	int x = direct.X() < 0 ? (-direct.X()*100):(direct.X()*100) ;

	int zs = (direct.Z() < 0 ? 1:0);
	int ys = (direct.Y() < 0 ? 3:0);
	int xs = (direct.X() < 0 ? 5:0);
	int s = zs + ys + xs;

	j = x*10000 + y*100 + z + s*1000000;
//----------------------------------------------------------------------------
	/*int z = direct.Z() < 0 ? (-direct.Z()*100):(direct.Z()*100) ;	
	int y = direct.Y() < 0 ? (-direct.Y()*100):(direct.Y()*100) ;
	int x = direct.X() < 0 ? (-direct.X()*1000):(direct.X()*1000) ;

	int zs = (direct.Z() < 0 ? 1:0);
	int ys = (direct.Y() < 0 ? 3:0);
	int xs = (direct.X() < 0 ? 5:0);
	int s = zs + ys + xs;

	j = x*10000 + y*100 + z + s*10000000; 
//----------------------------------------------------------------------------
	int z = direct.Z() < 0 ? (-direct.Z()*1000):(direct.Z()*1000) ;	
	int y = direct.Y() < 0 ? (-direct.Y()*1000):(direct.Y()*1000) ;
	int x = direct.X() < 0 ? (-direct.X()*1000):(direct.X()*1000) ;

	int zs = (direct.Z() < 0 ? 1:0);
	int ys = (direct.Y() < 0 ? 3:0);
	int xs = (direct.X() < 0 ? 5:0);
	int s = zs + ys + xs;

	j = x*1000000 + y*1000 + z + s*1000000000; */
	
	
/*	if( j < 0 ){
		int asd;
		asd = 67;
	}
	
	static int min;
	static int max;
	if (min == 0)
		min = j;
	if (min > j)
		min = j;
	if (max < j)
		max = j;*/

return j;
}



void HW2::psLightSource::addToShadowVec(Coordinates& c){

	Coordinates direct = c - position; 
	int cNorm = direct.norm();
	direct.makeUnitVec();
	
		
	int i = getIndex(direct);
	
	if (i < 0 || i >= 100000000)
		return ;
	
	

	
	/*if (ShadowPointsVecX[i] == 32000 && ShadowPointsVecY[i] == 32000 && ShadowPointsVecZ[i] == 32000){				
	    
				ShadowPointsVecX[i] = static_cast<short>(c.X()) ;
				ShadowPointsVecY[i] = static_cast<short>(c.Y());
				ShadowPointsVecZ[i] = static_cast<short>(c.Z()) ;
			}else{	
				Coordinates tmp( static_cast<double>(ShadowPointsVecX[i]),  static_cast<double>(ShadowPointsVecY[i]),  static_cast<double>(ShadowPointsVecZ[i]));
				Coordinates spv = tmp - position;
				if ((cNorm < spv.norm())){	
									
				ShadowPointsVecX[i] = static_cast<short>(c.X()) ;
				ShadowPointsVecY[i] = static_cast<short>(c.Y());
				ShadowPointsVecZ[i] = static_cast<short>(c.Z()) ;
					return;
				}
			
			}*/


			if (ShadowPointsVec[i].X() == 0 && ShadowPointsVec[i].Y() == 0 && ShadowPointsVec[i].Z() == 0){				
	            ShadowPointsVec[i] = c ;
			}else{	
				Coordinates spv = ShadowPointsVec[i] - position;
				if ((cNorm < spv.norm())){					
					ShadowPointsVec[i] = c;
					return;
				}
			
			}
		
}



#define TRESH 40
bool HW2::psLightSource::isShadowed(Coordinates& c){


	Coordinates direct = c - position; 
	int cNorm = direct.norm();
	direct.makeUnitVec();
	
	
	

	/*int i = getIndex(direct);
	if (i < 0 || i >= 100000000)
		return true;
	
	if ((ShadowPointsVecX[i] <= static_cast<short>(c.X()) + TRESH)&&(ShadowPointsVecX[i] >= static_cast<short>(c.X()) - TRESH)&&(ShadowPointsVecY[i] <= static_cast<short>(c.Y()) + TRESH)&&(ShadowPointsVecY[i] >= static_cast<short>(c.Y()) - TRESH)&&(ShadowPointsVecZ[i] <= static_cast<short>(c.Z()) + TRESH)&&(ShadowPointsVecZ[i] >= static_cast<short>(c.Z()) - TRESH)){
			return false;
		};*/
	
	
	int i = getIndex(direct);
	if (i < 0 || i > 1000000000)
		return true;
	
	//if ((ShadowPointsVec[i].X() <= c.X() + TRESH)&&(ShadowPointsVec[i].X() >= c.X() - TRESH)&&(ShadowPointsVec[i].Y() <= c.Y() + TRESH)&&(ShadowPointsVec[i].Y() >= c.Y() - TRESH)&&(ShadowPointsVec[i].Z() <= c.Z() + TRESH)&&(ShadowPointsVec[i].Z() >= c.Z() - TRESH)){
	if ((ShadowPointsVec[i] - c).norm()<60){
		

		if(shadowVerification < 40)
			shadowVerification++;
		
		
		
			
			
			if(shadowVerification > 20)
				 return false;
		    return true;
		}
		
		if(shadowVerification >-1 )
			shadowVerification--;	

	return true;

}